
package com.benimetum.managers;

import com.benimetum.database.Sparql;
import com.benimetum.exceptions.DatabaseConnectException;
import com.benimetum.exceptions.DatabaseWriteOrDeleteException;
import com.benimetum.items.Community;
import com.benimetum.items.Person;
import com.hp.hpl.jena.query.QuerySolution;
import com.hp.hpl.jena.query.ResultSet;
import com.hp.hpl.jena.query.ResultSetFormatter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;

/**
 *
 * @author Ethem Cem Ozkan
 * @email ethemcem.ozkan@gmail.com
 * No 07110604
 */
public class CommunityManager
{
    
    private final static String RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#";
    private final static String ETU="http://www.benimetum.com/benimetum.owl#";
    
    /**
     * grup oluşturur.
     */
    public static boolean create(String adminId, String name){
	  Random random=new Random();
	  String id="co"+random.nextInt(1000000000);
          
	  try {
		Sparql.insertProperty(ETU+id, RDF+"type", ETU+"Community");
		Sparql.insertProperty(ETU+adminId, ETU+"adminOf", ETU+id);
		Sparql.insertProperty(ETU+id, ETU+"createdBy", ETU+adminId);
		Sparql.insertLiteral(ETU+id, ETU+"id", id);		
		Sparql.insertLiteral(ETU+id, ETU+"name", name);

		addMember(id, adminId);
	  } catch (DatabaseConnectException ex) {
		return false;
	  } catch (DatabaseWriteOrDeleteException ex) {
		return false;
	  }
	  return true;
    }
    
    public static boolean delete(String id){
	  try {
		Person[] communityMembers = getCommunityMembers(id);
		Person communityAdmin = getCommunityAdmin(id);
		for (int i = 0; i < communityMembers.length; i++) {
		    deleteMember(id, communityMembers[i].getId());
		}
		    Sparql.removeLiteral(ETU+id, ETU+"id");		
		    Sparql.removeLiteral(ETU+id, ETU+"name");
		    Sparql.removeResource(ETU+communityAdmin.getId(), ETU+"adminOf", ETU+id);
		    Sparql.removeResource(ETU+id, ETU+"createdBy", ETU+communityAdmin.getId());
		    Sparql.removeResource(ETU+id, RDF+"type", ETU+"Community");
	  } catch (DatabaseWriteOrDeleteException ex) {
		return false;
	  } catch (DatabaseConnectException ex) {
		return false;
	  }
		return true;
    }
    
    public static boolean addMember(String groupId, String memberId){
	  try {
		Sparql.insertProperty(ETU+memberId, ETU+"memberOf", ETU+groupId);
		Sparql.insertProperty(ETU+groupId, ETU+"hasMembers", ETU+memberId);
	  } catch (DatabaseWriteOrDeleteException ex) {
		return false;
	  }
	  return true;
    }
    
    public static boolean deleteMember(String groupId, String memberId){
	  try {
		Sparql.removeResource(ETU+memberId, ETU+"memberOf", ETU+groupId);
		Sparql.removeResource(ETU+groupId, ETU+"hasMembers", ETU+memberId);
	  } catch (DatabaseConnectException ex) {
		return false;
	  } catch (DatabaseWriteOrDeleteException ex) {
		return false;
	  }
	  return true;
    }
    
    /**
     * idsi verilen topluluğu döndürür
     * @param communityId
     * @return 
     */
    public static Community getCommunityById(String communityId){
	  String query="select ?name ?id ?adminId where{?comm rdf:type etu:Community. ?comm etu:id \""+communityId+"\". ?comm etu:name ?name. ?comm etu:id ?id. ?comm etu:createdBy ?admin. ?admin etu:id ?adminId}";
	  ResultSet search = Sparql.search(query);
	  List<QuerySolution> toList = ResultSetFormatter.toList(search);
          Sparql.close();
	  if(!toList.isEmpty()){	
		String adminId=toList.get(0).get("adminId").toString();
		Person admin = null;
		if(adminId.startsWith("t"))
		    admin=TeacherManager.getTeacherById(adminId);
		else if(adminId.startsWith("st"))
		    admin=StudentManager.findStudentById(adminId);
		return new Community(communityId, toList.get(0).get("name").toString(), getCommunityMembers(communityId), admin);
	  }
	  return null;
    }
    
    public static Person[] getCommunityMembers(String communityId){
	  String query="select ?id where{?comm rdf:type etu:Community. ?comm etu:id \""+communityId+"\". ?comm etu:hasMembers ?person. ?person etu:id ?id}";
	  ResultSet search = Sparql.search(query);
	  List<QuerySolution> toList = ResultSetFormatter.toList(search);
          Sparql.close();
	  Iterator<QuerySolution> iterator = toList.iterator();
	  ArrayList<Person> members=new ArrayList<Person>();
	  while (iterator.hasNext()) {
		QuerySolution querySolution = iterator.next();
		String id=querySolution.get("id").toString();
		if(id.startsWith("t"))
		    members.add(TeacherManager.getTeacherById(id));
		else if(id.startsWith("st"))
		    members.add(StudentManager.findStudentById(id));
	  }
	  Person[] array=new Person[members.size()];
	  return members.toArray(array);
    }
    
    public static Person getCommunityAdmin(String communityId){
	  String query="select ?adminId where{?comm rdf:type etu:Community. ?comm etu:id \""+communityId+"\". ?comm etu:createdBy ?admin. ?admin etu:id ?adminId}";
	  ResultSet search = Sparql.search(query);
	  List<QuerySolution> toList = ResultSetFormatter.toList(search);
          Sparql.close();
	  if(!toList.isEmpty()){	
		String adminId=toList.get(0).get("adminId").toString();
		Person admin = null;
		if(adminId.startsWith("t"))
		    admin=TeacherManager.getTeacherById(adminId);
		else if(adminId.startsWith("st"))
		    admin=StudentManager.findStudentById(adminId);
		return admin;
	  }
	  return null;
    }
    
    public static boolean isAdminOf(String personId, String communityId){
	  String query="select ?comm where{?comm rdf:type etu:Community. ?comm etu:id \""+communityId+"\". ?comm etu:createdBy ?admin. ?admin etu:id \""+personId+"\".}";
	  ResultSet search = Sparql.search(query);
	  List<QuerySolution> toList = ResultSetFormatter.toList(search);
          Sparql.close();
	  return !toList.isEmpty();
    }
    
    public static boolean isMemberOf(String personId, String communityId){
	  String query="select ?id where{?comm rdf:type etu:Community. ?comm etu:id \""+communityId+"\". ?comm etu:hasMembers ?person. ?person etu:id \""+personId+"\".}";
	  ResultSet search = Sparql.search(query);
	  List<QuerySolution> toList = ResultSetFormatter.toList(search);
          Sparql.close();
	  return !toList.isEmpty();
    }
    
    public static Community[] getStudentsCommunitys(String personId){
	  String query="select ?name ?id ?adminId where{?student rdf:type etu:Student.?student etu:id \""+personId+"\". ?student etu:memberOf ?comm. ?comm etu:name ?name. ?comm etu:id ?id. ?comm etu:createdBy ?admin. ?admin etu:id ?adminId}";
	  ResultSet search = Sparql.search(query);
	  List<QuerySolution> toList = ResultSetFormatter.toList(search);
          Sparql.close();
	  ArrayList<Community> groups=new ArrayList<Community>();
	  Iterator<QuerySolution> iterator = toList.iterator();
	  while(iterator.hasNext()){
            QuerySolution next = iterator.next();
		String adminId=next.get("adminId").toString();
		Person admin = null;
		if(adminId.startsWith("t"))
		    admin=TeacherManager.getTeacherById(adminId);
		else if(adminId.startsWith("st"))
		    admin=StudentManager.findStudentById(adminId);
		groups.add(new Community(next.get("id").toString(), next.get("name").toString(), getCommunityMembers(next.get("id").toString()), admin));
	  }
	  Community[] array=new Community[groups.size()];
	  return groups.toArray(array);
    }
    
    public static Community[] getTeachersCommunitys(String personId){
	  String query="select ?name ?id ?adminId where{?student rdf:type etu:Teacher.?student etu:id \""+personId+"\". ?student etu:memberOf ?comm. ?comm etu:name ?name. ?comm etu:id ?id. ?comm etu:createdBy ?admin. ?admin etu:id ?adminId}";
	  ResultSet search = Sparql.search(query);
	  List<QuerySolution> toList = ResultSetFormatter.toList(search);
          Sparql.close();
	  ArrayList<Community> groups=new ArrayList<Community>();
	  Iterator<QuerySolution> iterator = toList.iterator();
	  while(iterator.hasNext()){
            QuerySolution next = iterator.next();
		String adminId=next.get("adminId").toString();
		Person admin = null;
		if(adminId.startsWith("t"))
		    admin=TeacherManager.getTeacherById(adminId);
		else if(adminId.startsWith("st"))
		    admin=StudentManager.findStudentById(adminId);
		groups.add(new Community(next.get("id").toString(), next.get("name").toString(), getCommunityMembers(next.get("id").toString()), admin));
	  }
	  Community[] array=new Community[groups.size()];
	  return groups.toArray(array);
    }
    
   
    public static Community[] getAllCommunities(){
          String query="select ?id ?name ?adminId where{?comm rdf:type etu:Community.?comm etu:name ?name. ?comm etu:id ?id. ?comm etu:createdBy ?admin. ?admin etu:id ?adminId}";
	  ResultSet search = Sparql.search(query);
	  List<QuerySolution> toList = ResultSetFormatter.toList(search);
          Sparql.close();
	  ArrayList<Community> groups=new ArrayList<Community>();
        Iterator<QuerySolution> iterator = toList.iterator();
	  while(iterator.hasNext()){
            QuerySolution next = iterator.next();
		String adminId=next.get("adminId").toString();
		Person admin = null;
		if(adminId.startsWith("t"))
		    admin=TeacherManager.getTeacherById(adminId);
		else if(adminId.startsWith("st"))
		    admin=StudentManager.findStudentById(adminId);
		groups.add(new Community(next.get("id").toString(), next.get("name").toString(), getCommunityMembers(next.get("id").toString()), admin));
	  }
	  Community[] array=new Community[groups.size()];
	  return groups.toArray(array);
    
    }
    
    public static Community[] getCommunitysByAdminId(String adminId){
	  String query="select ?name ?id ?adminId where{?comm rdf:type etu:Community. ?comm etu:name ?name. ?comm etu:id ?id. ?comm etu:createdBy ?admin. ?admin etu:id \""+adminId+"\".}";
	  ResultSet search = Sparql.search(query);
	  List<QuerySolution> toList = ResultSetFormatter.toList(search);
          Sparql.close();
	  ArrayList<Community> groups=new ArrayList<Community>();
	  Iterator<QuerySolution> iterator = toList.iterator();
	  while(iterator.hasNext()){
            QuerySolution next = iterator.next();
		Person admin = null;
		if(adminId.startsWith("t"))
		    admin=TeacherManager.getTeacherById(adminId);
		else if(adminId.startsWith("st"))
		    admin=StudentManager.findStudentById(adminId);
		groups.add(new Community(next.get("id").toString(), next.get("name").toString(), getCommunityMembers(next.get("id").toString()), admin));
	  }
	  Community[] array=new Community[groups.size()];
	  return groups.toArray(array);
    }
    public static boolean deleteCommunity(String communityId){return true;}
    
}
